import {_decorator, Component, Node} from 'cc';
import OrderManager from '../manager/OrderManager';
import StorageManager from '../manager/StorageManager';
import {progress} from './progress';
import {CardPoolMgr} from '../manager/CardPoolMgr';
import {TableMgr} from '../manager/TableMgr';
import {OrderPoolMgr} from '../manager/OrderPoolMgr';
import {GameStatus} from '../GameDef';
import {GameEvent} from '../event/GameEvent';
import EventCenter from '../event/EventCenter';
import {Combo} from './Combo';
import {LevelMgr} from '../manager/LevelMgr';


const {ccclass, property} = _decorator;

@ccclass('Game')
export default class Game extends Component {

    @property(OrderManager)
    orderManager: OrderManager;

    @property(TableMgr)
    tableMgr: TableMgr;

    @property(StorageManager)
    storageManager: StorageManager;

    @property(progress)
    progress: progress;

    @property(Combo)
    combo: Combo;

    @property(Node)
    gameWin: Node = null;

    @property(Node)
    gameOver: Node = null;



    _curLevel: number = 1;
    _gameStatus:GameStatus = GameStatus.NONE;

    _messageQueue: any[] = [];

    get curLevel() {
        return this._curLevel;
    }

    get isGameEnd() {
        return this._gameStatus == GameStatus.FINISH;
    }

    get isGameRunning() {
        return this._gameStatus == GameStatus.PLAYING;
    }

    get status(): GameStatus {
        return this._gameStatus;
    }

    set status(value: GameStatus) {
        this._gameStatus = value;
    }

    async onLoad() {
        this.init();
    }

    protected onEnable(): void {
        this.addListener();
    }

    protected onDisable(): void {
        this.destroyListener();
    }

    async init(){
        await this.initData();
        this.initUI();

        this.scheduleOnce(()=>{
            this.startGame(); 
        });
    }

    async initData() {
        // 牌库初始
        const lm = LevelMgr.getInstance();
        await CardPoolMgr.getInstance().load(lm.getPoolFileName());
        await OrderPoolMgr.getInstance().load(lm.getOrdersFileName())

        await this.tableMgr.initData(lm.getMapFileName());
        this.storageManager.initData();
        this.orderManager.initData();
    }

    initUI() {
        this.progress.setGoal(OrderPoolMgr.getInstance().size);
        this.tableMgr.initUI();
        this.storageManager.initUI()
        this.orderManager.initUI()
    }

    async reset() {
        this.gameWin.active = false;
        this.gameOver.active = false;
    }

    startGame() {
       this.status = GameStatus.PLAYING;

       this.orderManager.tryGetOrder();
    }

    tryCardUse(cardUid:number){
        if(!this.isGameRunning)
            return;

        let card = CardPoolMgr.getInstance().getCardById(cardUid);

        let [orderUid,fitIndex] = this.orderManager.checkOrder(card);

        this.tableMgr.removeCardByUid(cardUid)
        this.storageManager.removeCardByUid(cardUid)

        if(!orderUid) {
            let [nodeParent,pos] = this.storageManager.addCard(card)
            this.storageManager.refreshUI()
            if(this.storageManager.checkGameOver()) {
                this.onGameOver();
            }
        }else{
            let fixCardUid = this.orderManager.onCardAdd(card,orderUid,fitIndex)
            if(fixCardUid){
                this.tableMgr.fixCard(fixCardUid, orderUid)
            }
        }
    }

    private tryNewOrder() {
        if(!this.isGameRunning)
            return;
        this.orderManager.tryGetOrder();

        this.checkStorage()
        this.setProgress()

        let isGameWin = OrderPoolMgr.getInstance().unFinishedOrdersCount == 0;
        if(isGameWin)
            this.onGameWin()
    }

    private addListener() {
        EventCenter.on(GameEvent.CardClick, this.tryCardUse, this);
        EventCenter.on(GameEvent.OrderUnlock,this.tryNewOrder,this)
        EventCenter.on(GameEvent.OrderComplete,this.tryNewOrder,this)
    }

    private destroyListener() {
        EventCenter.off(GameEvent.CardClick, this.tryCardUse, this);
        EventCenter.off(GameEvent.OrderUnlock,this.tryNewOrder,this)
        EventCenter.off(GameEvent.OrderComplete,this.tryNewOrder,this)
    }

    onClickMoveOut() {
        this.storageManager.moveOut()
    }

    nextLevel() {
        LevelMgr.getInstance().next();
        this.reset();
        this.init();
    }

    onClickShuffle() {
        this.tableMgr.shuffle()
    }

    onClickTips() {
        const b = this.tableMgr.tips()
        if(!b) {
           console.log('没有可用的牌')
        }
    }

    restartCurLevel(){
        this.reset();
        this.init();
    }

    private checkStorage() {
        let UCards = this.storageManager.getStorage()
        for(let UCard of UCards){
            let cardData = CardPoolMgr.getInstance().getCardById(UCard.uid);
            let isToOrder = this.orderManager.checkOrder(cardData)
            if(isToOrder.length){
                EventCenter.emit(GameEvent.CardClick, UCard.uid)
                break;
            }
        }
    }

    private setProgress() {
        let newCount = OrderPoolMgr.getInstance().finishedOrdersCount;
        if(newCount > this.progress.progress){
            this.progress.setProgress(newCount);
            this.combo.setCombo(newCount);
        }
    }

    private onGameWin() {
        console.log('Game win');
        this.status = GameStatus.FINISH;
        this.gameWin.active = true;
    }

    private onGameOver() {
        this.status = GameStatus.FINISH;
        this.gameOver.active = true;
    }


}